package main;

import java.util.LinkedList;

public class FunctionalUnit extends Main{

	
	char type;
	int noOfCycles;
	LinkedList<Instruction> instructions;  
	
	
	public FunctionalUnit(char type, int noOfCycles) {
		
		this.type = type;
		this.noOfCycles = noOfCycles;
		instructions = new LinkedList<Instruction>();
	}
	
	public int getResult(int x, int y){
		
		switch(type) {
		
		case 'a' : return x + y;
		case 'n' : return x &~ y;
		case 'm' : return x * y;
		case 'd' : if(y == 0) return Short.MAX_VALUE; 
		else return x / y;
		
		}
		return 0;
	}
	
	public void execute() {
		
		if(instructions.isEmpty()) return;
		
		Instruction i = instructions.getFirst();
		
		if(!i.inExecution) {i.inExecution = true; return;}
		
		i.N++;
		
		if(i.N == noOfCycles) {broadCastResult();} 
		
		
	}
	
	void broadCastResult() {
		
		Instruction ins = instructions.removeFirst();
		
		if(!instructions.isEmpty()) instructions.getFirst().inExecution = true;
		
		int physicalReg = (ins.dest);
		int result;
		
		if(ins.type.equals("ADDI")) result = getResult(ins.v1,ins.immediate);
		else result = getResult(ins.v1,ins.v2);
		
		int robIndex = RegRobMapping.get(ins.dest).value;
		
		ResStationEntry e2 = null;
		
		for(int i=0; i<ReservationSation.size(); i++) {
			
			ResStationEntry e = ReservationSation.get(i);
			if(e.inst == ins) e2 = e;		
			
			if(e.inst.source1 == physicalReg) {
				
				e.r1 = true;
				e.v1 = result;
				e.inst.v1 = result;
			}
			
			if(e.inst.source2 == physicalReg) {
				
				e.r2 = true;
				e.v2 = result;
				e.inst.v2 = result;
			}
			
			
		}
		
		//Write in ROB
		ROB.get(robIndex).value = result;
		
		ReservationSation.remove(e2);
		reserve--;
		Execute.stageInstructions.add(ins);
		
	}

	public boolean map(String s) {
		
		//if(type == 'a' && (s.equals("ADD") || s.equals("ADDI") 
		//	|| s.equals("LW") || s.equals("SW") || s.equals("JMP") || s.equals("JALR")));
		
		if(type == 'n' && (s.equals("NAND") || s.equals("BEQ"))) return true;
		
		if(type == 'm' && s.equals("MUL")) return true;
		
		if(type == 'd' && s.equals("DIV")) return true;
		
		if(type == 'a' && !(s.equals("NAND") || s.equals("BEQ")
			|| s.equals("MUL") || s.equals("DIV"))) return true;
		
		return false;
		
		
	}
	
}
